    //Random Game Engine
    //Copyright (C) 2012  Nikolay Dionisov

    //This program is free software: you can redistribute it and/or modify
    //it under the terms of the GNU General Public License as published by
    //the Free Software Foundation, either version 3 of the License, or
    //(at your option) any later version.

    //This program is distributed in the hope that it will be useful,
    //but WITHOUT ANY WARRANTY; without even the implied warranty of
    //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    //GNU General Public License for more details.

    //You should have received a copy of the GNU General Public License
    //along with this program.  If not, see <http://www.gnu.org/licenses/>.

	//------------------------------------------------------------------------

	//FILE NAME: WinFramework.h
	//Definition of the end windows framework.
	//Creating renderer, and making sure there is a window so it can "draw" somewhere.
	//For encapsulation purposes, all connections with the OS are done here.

#include "..\BaseFramework.h"
#include <Windows.h>
namespace re
{
	namespace core
	{
		template<class T>
		class WindowsFramework : public BaseOSFramework<T>
		{
		public:
			WindowsFramework() {}
			~WindowsFramework() {}

			void CreateThread(IThreadForwarder * thread_forwarder)
			{
				if(::CreateThread(0, 0, ThreadBegin, thread_forwarder, 0, 0) == NULL)
				{
					int error = 0;
				}
			}
		private:
			static DWORD WINAPI ThreadBegin(LPVOID param)
			{
				reinterpret_cast<IThreadForwarder*>(param)->FollowThread();
				delete param;
				return 0;
			}
		public:
			virtual IRenderer* VCreateRenderer()
			{
				return NULL;
			}
			void VRun()
			{
				MSG msg;
				while(GetMessage(&msg, 0, 0, 0))
				{
					if(!p_settings_->is_running)
					{
						break;
					}
					TranslateMessage(&msg);
					DispatchMessage(&msg);
					if(CallbackUpdate())
					{
						CallbackRender();
					}
				}
			}
			void VCreateMainWindow()
			{
				std::wstring class_name(p_settings_->app_name.begin(), p_settings_->app_name.end());
				WNDCLASSEX wcex;

				wcex.cbSize = sizeof(WNDCLASSEX);
				wcex.style          = CS_HREDRAW | CS_VREDRAW;
				wcex.lpfnWndProc    = WndProc;
				wcex.cbClsExtra     = 0;
				wcex.cbWndExtra     = 0;
				wcex.hInstance      = GetModuleHandle(0);
				wcex.hIcon          = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
				wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
				wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
				wcex.lpszMenuName   = NULL;
				wcex.lpszClassName  = class_name.c_str();
				wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));

				if (!RegisterClassEx(&wcex))
				{
					MessageBox(NULL,
						L"Call to RegisterClassEx failed!",
						L"FAIL!",
						NULL);

					return;
				}


				hwnd_ = CreateWindow(class_name.c_str(), class_name.c_str(), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 
					p_settings_->width, p_settings_->height, NULL, NULL, wcex.hInstance, NULL);

				ShowWindow(hwnd_, 10);
				UpdateWindow(hwnd_);

			}
			void VDestroyMainWindow()
			{
				DestroyWindow(hwnd_);
				UnregisterClass((LPCWSTR)(p_settings_->app_name.c_str()), GetModuleHandle(NULL));
			}
		private:
			static HRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
			{
				return dynamic_cast<WindowsFramework<T>*>(g_framework)->WndProcMember(hwnd, msg, wparam, lparam);
			}
			HRESULT WndProcMember( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
			{
				switch(msg)
				{
				case WM_DESTROY:
					PostQuitMessage(0);
					break;
				default:
					return DefWindowProc(hwnd, msg, wparam, lparam);
					break;
				}
				return 0; // avoid warning
			}

			//current window
			HWND hwnd_;
		};

	}
}